home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Prog
/
T
/
TIFF Code.cpt
/
tifflib.c
< prev
next >
Wrap
Text File
|
1987-12-21
|
33KB
|
1,445 lines
/*
* tifflib.c - Copyright (c) 1987 by Bear River Associates, Inc.
*
* MPW C Version
*/
/* Standard C Include files */
#include "ErrNo.h"
#include "StdIO.h"
/* Primary Interface Files */
#include "Types.h"
#include "Resources.h"
#include "Quickdraw.h"
#include "Windows.h"
#include "OSUtils.h"
#include "ToolUtils.h"
#include "TextEdit.h"
#include "Controls.h"
/* Other Interface files */
#include "Dialogs.h"
#include "Errors.h"
#include "Events.h"
#include "Files.h"
#include "Memory.h"
#include "Packages.h"
/* Application-specific Include files */
#include "tifflib.h"
/* Local Routine Declarations */
OSErr InsertTag();
OSErr HdlInsertTag();
OSErr DeleteTag();
OSErr GStripArrays();
OSErr PutStripArrays();
OSErr GStripParams();
void ParseTag();
void SwapWord();
void SwapLong();
/* External Routine Declarations */
OSErr AllocPtr();
OSErr AllocMemory();
OSErr AllocHandleSize();
/* **************************************************************** */
TIFFLoader()
{
}
/* ------------------------------------------------------------------- */
/*
* Writes or re-writes the header; the value of dirOffset
* is the offset of the first directory.
*/
OSErr TWriteHeader(refNum, dirOffset, byteOrder)
Int16 refNum;
Int32 dirOffset; /* offset of first directory */
Int16 byteOrder;
{
OSErr error;
TiffHeader header;
Int32 count;
error = noErr;
header.byteOrder = byteOrder;
header.version = LEGAL_VERSION;
header.dirOffset = dirOffset;
if (byteOrder == INTEL)
{
SwapWord(&header.version);
SwapLong(&header.dirOffset);
}
error = SetFPos(refNum, fsFromStart, 0L);
count = sizeof(TiffHeader);
if (error == noErr)
error = FSWrite(refNum, &count, &header);
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Reads header, returns offset of the first image file directory and the
* byte order of the file.
*/
OSErr TReadHeader(refNum, dirOffset, byteOrder)
Int16 refNum;
Int32 *dirOffset;
Int16 *byteOrder;
{
OSErr error;
TiffHeader header;
Int32 count;
error = SetFPos(refNum, fsFromStart, 0L);
count = sizeof(TiffHeader);
if (error == noErr)
error = FSRead(refNum, &count, &header);
if (header.byteOrder == INTEL)
SwapLong(&header.dirOffset);
*dirOffset = header.dirOffset;
*byteOrder = header.byteOrder;
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Add tag to list. If tag already present, update length and value.
* This routine keeps tags in correct order in list.
*/
OSErr TPutPtrTag(listHandle, tagNo, tagType, nVals, value)
Handle listHandle;
Int16 tagNo;
Int16 tagType;
Int32 nVals;
unsigned char *value;
{
Int32 pointer;
OSErr error;
error = noErr;
pointer = 0L;
if (TFindTag(listHandle, &pointer, tagNo))
error = DeleteTag(listHandle, pointer);
if (error == noErr)
error = InsertTag(listHandle, pointer, tagNo, tagType, nVals, value);
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Add tag to list. Value for tag is in a handle block.
* If tag already present, update length and value.
* This routine keeps tags in correct order in list.
*/
OSErr TPutHdlTag(listHandle, tagNo, tagType, nVals, valueHdl)
Handle listHandle;
Int16 tagNo;
Int16 tagType;
Int32 nVals;
unsigned char **valueHdl;
{
Int32 pointer;
OSErr error;
error = noErr;
pointer = 0L;
if (TFindTag(listHandle, &pointer, tagNo))
error = DeleteTag(listHandle, pointer);
if (error == noErr)
error = HdlInsertTag(listHandle, pointer, tagNo, tagType,
nVals, valueHdl);
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Searches list for tag of specified number.
* If found, returns TRUE, and pointer contains offset of tag in list.
* If not found, returns FALSE, and pointer contains offset in list where
* tag would be inserted.
*/
Boolean TFindTag(listHandle, pointer, tagNo)
Handle listHandle;
Int32 *pointer;
Int16 tagNo;
{
Boolean done;
Int32 listSize;
Int16 thisTagNo;
Int16 tagType;
Int32 length;
Int32 nVals;
*pointer = 0L;
listSize = GetHandleSize(listHandle);
done = FALSE;
while (*pointer < listSize && !done)
{
ParseTag(listHandle, *pointer, &thisTagNo, &tagType, &nVals);
switch(tagType)
{
case BYTE:
length = nVals * BYTESIZE;
break;
case ASCII:
length = nVals * ASCIISIZE;
break;
case SHORT:
length = nVals * SHORTSIZE;
break;
case LONG:
length = nVals * LONGSIZE;
break;
case RATIONAL:
length = nVals * RATSIZE;
break;
default:
done = TRUE;
break;
}
if (thisTagNo < tagNo)
(*pointer) += 8 + length;
else
done = TRUE;
}
return(done && (tagNo == thisTagNo));
}
/* ------------------------------------------------------------------- */
/*
* Returns value of tag. Tag is specified by listHandle and pointer.
*/
void TGetTag(listHandle, pointer, value, valueSize)
Handle listHandle;
Int32 pointer;
Ptr value;
Int32 valueSize;
{
Int16 tagNo;
Int16 tagType;
Int32 length;
Int32 nVals;
Int32 i;
Ptr listPtr;
Ptr valuePtr;
ParseTag(listHandle, pointer, &tagNo, &tagType, &nVals);
switch(tagType)
{
case BYTE:
length = nVals * BYTESIZE;
break;
case ASCII:
length = nVals * ASCIISIZE;
break;
case SHORT:
length = nVals * SHORTSIZE;
break;
case LONG:
length = nVals * LONGSIZE;
break;
case RATIONAL:
length = nVals * RATSIZE;
break;
default:
length = 0L;
break;
}
valuePtr = value;
listPtr = *listHandle + pointer + 8; /* DEREFERENCING HANDLE */
for (i=0; i<length && i<valueSize; i++)
*valuePtr++ = *listPtr++;
}
/* ------------------------------------------------------------------- */
/*
* Read tags from file, from directory at offset thisDirPointer.
* Create and return a handle to the tag data. Return offset to next
* directory in nextDirPointer.
*/
OSErr TReadTags(refNum, byteOrder, listHandle, thisDirPointer, nextDirPointer)
Int16 refNum;
Int16 byteOrder;
Handle *listHandle;
Int32 thisDirPointer;
Int32 *nextDirPointer;
{
OSErr error;
Int32 count;
Int16 entryCount;
Int16 thisEntry;
Int16 tagNo;
Int16 tagType;
Int32 nVals;
Int32 length;
Int32 valOffset;
Int32 listPointer;
Int32 nextDirEntry;
Ptr tempBuffer;
Int32 k;
Handle tempHandle;
*listHandle = NIL;
error = AllocMemory(listHandle, 0L);
if (error == noErr)
error = SetFPos(refNum, fsFromStart, thisDirPointer);
if (error == noErr)
{
count = sizeof(Int16);
error = FSRead(refNum, &count, &entryCount);
if (byteOrder == INTEL)
SwapWord(&entryCount);
}
thisEntry = 0;
listPointer = 0L;
nextDirEntry = thisDirPointer + 2;
while (thisEntry++ < entryCount && error == noErr)
{
error = SetFPos(refNum, fsFromStart, nextDirEntry);
count = 2;
if (error == noErr)
error = FSRead(refNum, &count, &tagNo);
if (byteOrder == INTEL)
SwapWord(&tagNo);
count = 2;
if (error == noErr)
error = FSRead(refNum, &count, &tagType);
if (byteOrder == INTEL)
SwapWord(&tagType);
count = 4;
if (error == noErr)
error = FSRead(refNum, &count, &nVals);
if (byteOrder == INTEL)
SwapLong(&nVals);
switch(tagType)
{
case BYTE:
length = nVals * BYTESIZE;
break;
case ASCII:
length = nVals * ASCIISIZE;
break;
case SHORT:
length = nVals * SHORTSIZE;
break;
case LONG:
length = nVals * LONGSIZE;
break;
case RATIONAL:
length = nVals * RATSIZE;
break;
default:
error = -3;
break;
}
count = 4;
if (error == noErr)
error = FSRead(refNum, &count, &valOffset);
if (length > 4)
{
if (byteOrder == INTEL)
SwapLong(&valOffset);
tempBuffer = NIL;
if (error == noErr)
error = AllocPtr(&tempBuffer, length);
if (error == noErr)
error = SetFPos(refNum, fsFromStart, valOffset);
count = length;
if (error == noErr)
error = FSRead(refNum, &count, tempBuffer);
if (error == noErr && byteOrder == INTEL)
switch(tagType)
{
case SHORT:
for (k=0; k<nVals; k++)
SwapWord(&((Int16 *)tempBuffer)[k]);
break;
case LONG:
for (k=0; k<nVals; k++)
SwapLong(&((Int32 *)tempBuffer)[k]);
break;
case RATIONAL:
for (k=0; k<nVals; k++)
{
SwapLong(&((Int32 *)tempBuffer)[2*k]);
SwapLong(&((Int32 *)tempBuffer)[2*k + 1]);
}
break;
}
if (error == noErr)
error = TPutPtrTag(*listHandle, tagNo, tagType, nVals, tempBuffer);
if (tempBuffer != NIL)
DisposPtr(tempBuffer);
}
else
{
if (byteOrder == INTEL)
switch(tagType)
{
case SHORT:
for (k=0; k<nVals; k++)
SwapWord(&((Int16 *)&valOffset)[k]);
break;
case LONG:
SwapLong(&valOffset);
break;
}
if (error == noErr)
error = TPutPtrTag(*listHandle, tagNo, tagType,
nVals, &valOffset);
}
nextDirEntry += 12;
}
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Write tag data from listHandle out to file, beginning at
* offset *nextFileFree. Update nextFileFree to logical end-of-file.
* Put nextDirPointer at end of tag directory as value of offset to
* the next tag directory.
*/
OSErr TWriteTags(refNum, byteOrder, nextFileFree, listHandle, nextDirPointer)
Int16 refNum;
Int16 byteOrder;
Int32 *nextFileFree;
Handle *listHandle;
Int32 nextDirPointer;
{
OSErr error;
Int32 count;
Int32 listSize;
Int16 tagNo;
Int16 tagType;
Int32 length;
Int32 nVals;
Int16 thisEntry;
Int16 entryCount;
Int32 listPointer;
Int32 nextDirEntry;
UInt32 valOffset;
Int32 i;
Int32 k;
UInt16 temp16;
UInt32 temp32;
Ptr tempPtr;
Handle tempHandle;
error = noErr;
listPointer = 0L;
listSize = GetHandleSize(listHandle);
/* count the number of directory entries (number of tags) */
entryCount = 0;
while (listPointer < listSize && error == noErr)
{
ParseTag(listHandle, listPointer, &tagNo, &tagType, &nVals);
switch(tagType)
{
case BYTE:
length = nVals * BYTESIZE;
break;
case ASCII:
length = nVals * ASCIISIZE;
break;
case SHORT:
length = nVals * SHORTSIZE;
break;
case LONG:
length = nVals * LONGSIZE;
break;
case RATIONAL:
length = nVals * RATSIZE;
break;
default:
error = -3;
break;
}
listPointer += 8 + length;
entryCount++;
}
if (error == noErr)
error = SetFPos(refNum, fsFromStart, *nextFileFree);
count = 2;
temp16 = entryCount;
if (byteOrder == INTEL)
SwapWord(&temp16);
if (error == noErr)
error = FSWrite(refNum, &count, &temp16);
/* offset for the first tag to be written */
nextDirEntry = *nextFileFree + 2;
/* set nexFileFree to point past this IFD */
*nextFileFree += 2 + entryCount * 12 + 4;
count = entryCount * 12 + 4;
/* expand file to fit IFD */
if (error == noErr)
error = SetEOF(refNum, *nextFileFree);
/* write out the tags */
thisEntry = 0;
listPointer = 0L;
while (thisEntry++ < entryCount && error == noErr)
{
error = SetFPos(refNum, fsFromStart, nextDirEntry);
ParseTag(listHandle, listPointer, &tagNo, &tagType, &nVals);
switch(tagType)
{
case BYTE:
length = nVals * BYTESIZE;
break;
case ASCII:
length = nVals * ASCIISIZE;
break;
case SHORT:
length = nVals * SHORTSIZE;
break;
case LONG:
length = nVals * LONGSIZE;
break;
case RATIONAL:
length = nVals * RATSIZE;
break;
default:
error = -3;
break;
}
count = 2;
temp16 = tagNo;
if (byteOrder == INTEL)
SwapWord(&temp16);
if (error == noErr)
error = FSWrite(refNum, &count, &temp16);
count = 2;
temp16 = tagType;
if (byteOrder == INTEL)
SwapWord(&temp16);
if (error == noErr)
error = FSWrite(refNum, &count, &temp16);
count = 4;
temp32 = nVals;
if (byteOrder == INTEL)
SwapLong(&temp32);
if (error == noErr)
error = FSWrite(refNum, &count, &temp32);
if (length <= 4) /* put actual value in directory entry */
{
valOffset = 0L;
TGetTag(listHandle, listPointer, &valOffset, length);
count = 4;
temp32 = valOffset;
if (byteOrder == INTEL)
{
switch(tagType)
{
case SHORT:
for (k=0; k<nVals; k++)
SwapWord(&((Int16 *)&temp32)[k]);
break;
case LONG:
SwapLong(&temp32);
break;
}
}
if (error == noErr)
error = FSWrite(refNum, &count, &temp32);
}
else /* offset of value goes in directory entry */
{
valOffset = *nextFileFree;
count = 4;
temp32 = valOffset;
if (byteOrder == INTEL)
SwapLong(&temp32);
if (error == noErr)
error = FSWrite(refNum, &count, &temp32);
if (error == noErr)
error = SetFPos(refNum, fsFromStart, *nextFileFree);
count = length;
tempPtr = NIL;
if (error == noErr)
error = AllocPtr(&tempPtr, length);
if (error == noErr)
TGetTag(listHandle, listPointer, tempPtr, length);
if (error == noErr && byteOrder == INTEL)
switch(tagType)
{
case SHORT:
for (k=0; k<nVals; k++)
SwapWord(&((Int16 *)tempPtr)[k]);
break;
case LONG:
for (k=0; k<nVals; k++)
SwapLong(&((Int32 *)tempPtr)[k]);
break;
case RATIONAL:
for (k=0; k<nVals; k++)
{
SwapLong(&((Int32 *)tempPtr)[2*k]);
SwapLong(&((Int32 *)tempPtr)[2*k + 1]);
}
break;
}
if (error == noErr)
error = FSWrite(refNum, &count, tempPtr);
*nextFileFree += length;
if (tempPtr != NIL)
DisposPtr(tempPtr);
}
nextDirEntry += 12;
listPointer += 8 + length;
}
if (error == noErr)
error = SetFPos(refNum, fsFromStart, nextDirEntry);
count = 4;
temp32 = nextDirPointer;
if (byteOrder == INTEL)
SwapLong(&temp32);
if (error == noErr)
error = FSWrite(refNum, &count, &temp32);
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Reads in "numLines" lines from the file starting with line number
* "startLine". The data for the lines will be places at the address
* specified by bufferPtr.
*/
OSErr TReadImage(refNum, listHandle, startLine, bufferPtr, numLines, plane)
Int16 refNum;
Handle listHandle;
Int32 startLine;
Ptr bufferPtr;
Int32 numLines;
Int16 plane; /* ignored, for now */
{
Handle countHandle;
Handle offsetHandle;
OSErr error;
Int32 pointer;
Int32 tRowsPerStrip;
Int16 tRowBytes;
Int16 bitsPerSample;
Int16 imageWidth;
Int16 imageLength;
Int16 compressType;
Int16 firstStrip;
Int16 lastStrip;
Int16 stripNum;
Ptr stripPtr;
Ptr dummyPtr;
Int32 stripSize;
Int32 stripOffset;
Ptr srcPtr;
Ptr dstPtr;
register Ptr rSrcPtr;
register Ptr rDstPtr;
Int32 count;
Int16 i;
Int32 thisLine;
Handle tempHandle;
error = GStripArrays(listHandle, &offsetHandle, &countHandle);
if (error == noErr)
error = GStripParams(listHandle, &tRowsPerStrip,
&imageWidth, &imageLength, &compressType, &bitsPerSample);
tRowBytes = ((Int32)imageWidth * bitsPerSample + 7) / 8;
/* NOTE! this can be an odd number, unlike bitMap.rowBytes */
dummyPtr = NIL;
if (error == noErr)
error = AllocPtr(&dummyPtr, (Int32)tRowBytes);
if (error == noErr)
{
firstStrip = startLine / tRowsPerStrip;
lastStrip = (startLine + numLines - 1) / tRowsPerStrip;
thisLine = firstStrip * tRowsPerStrip;
for (stripNum = firstStrip; stripNum <= lastStrip && error == noErr;
stripNum++)
{
stripSize = (*(Int32 **)countHandle)[stripNum];
stripOffset = (*(Int32 **)offsetHandle)[stripNum];
stripPtr = NIL;
error = AllocPtr(&stripPtr, stripSize);
if (error == noErr)
error = SetFPos(refNum, fsFromStart, stripOffset);
if (error == noErr)
{
count = stripSize;
error = FSRead(refNum, &count, stripPtr);
}
if (error == noErr)
{
srcPtr = stripPtr;
while (srcPtr < stripPtr + stripSize &&
thisLine < startLine + numLines && error == noErr)
{
if (thisLine < startLine)
dstPtr = dummyPtr;
else if (thisLine == startLine)
dstPtr = bufferPtr;
switch (compressType)
{
case 1:
rSrcPtr = srcPtr;
rDstPtr = dstPtr;
for (i=0; i<tRowBytes; i++)
*rDstPtr++ = *rSrcPtr++;
srcPtr = rSrcPtr;
dstPtr = rDstPtr;
break;
case 2:
error = HDecode(&dstPtr, &srcPtr, imageWidth);
break;
default:
error = -3;
break;
}
thisLine++;
}
}
if (stripPtr != NIL)
DisposPtr(stripPtr);
}
}
if (offsetHandle != NIL)
DisposHandle(offsetHandle);
if (countHandle != NIL)
DisposHandle(countHandle);
if (dummyPtr != NIL)
DisposPtr(dummyPtr);
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Writes image data for ONE strip. startpos must be start of a strip.
* numLines must be <= tRowsPerStrip.
* Strip parameters (rowsPerStrip, imageWidth,
* compressType and imageLength) must already have tags
*/
OSErr TWriteImageStrip(refNum, nextFileFree, listHandle,
startLine, numLines, bufferPtr, plane)
Int16 refNum;
Int32 *nextFileFree;
Handle listHandle;
Int32 startLine;
Int32 numLines;
Ptr bufferPtr;
Int16 plane;
{
OSErr error;
OSErr tempErr;
Int32 ** offsetHandle;
Int32 ** countHandle;
Int16 stripNum;
Int16 numStrips;
Int16 row;
Int16 i;
Int32 tRowsPerStrip;
Int16 tRowBytes;
Int16 bitsPerSample;
Int16 imageWidth;
Int16 imageLength;
Int16 compressType;
Int32 stripSize;
Int32 count;
Ptr srcPtr;
Ptr dstPtr;
register Ptr rSrcPtr;
register Ptr rDstPtr;
Ptr rowBuffer;
Int32 thisLine;
Handle tempHandle;
error = noErr;
if (GStripArrays(listHandle, &offsetHandle, &countHandle) != noErr)
{ /* if offsetHandle and countHandle don't exist, then create them */
error = AllocMemory(&offsetHandle, 0L);
if (error == noErr)
error = AllocMemory(&countHandle, 0L);
}
if (error == noErr)
error = GStripParams(listHandle, &tRowsPerStrip, &imageWidth,
&imageLength, &compressType, &bitsPerSample);
if (tRowsPerStrip > imageLength)
tRowsPerStrip = imageLength;
stripNum = startLine / tRowsPerStrip;
if (error == noErr)
{
numStrips = GetHandleSize(offsetHandle) / sizeof(Int32);
if (stripNum >= numStrips)
{
error = AllocHandleSize(offsetHandle,
(Size)(stripNum + 1) * sizeof(Int32));
if (error == noErr)
error = AllocHandleSize(countHandle,
(Size)(stripNum + 1) * sizeof(Int32));
if (error == noErr)
for (i=numStrips; i<stripNum; i++)
(*countHandle)[i] = 0L;
}
}
tRowBytes = (imageWidth * bitsPerSample + 7) / 8;
/* NOTE! this can be an odd number, unlike bitMap.rowBytes */
rowBuffer = NIL;
if (error == noErr)
error = AllocPtr(&rowBuffer, 2 * (Int32)tRowBytes);
if (error == noErr)
{
(*offsetHandle)[stripNum] = *nextFileFree;
stripSize = 0L;
srcPtr = bufferPtr;
error = SetFPos(refNum, fsFromStart, *nextFileFree);
for (row=0; row<tRowsPerStrip && row<numLines && error == noErr; row++)
{
dstPtr = rowBuffer;
switch (compressType)
{
case 1:
rSrcPtr = srcPtr;
rDstPtr = dstPtr;
for (i=0; i<tRowBytes; i++)
*rDstPtr++ = *rSrcPtr++;
srcPtr = rSrcPtr;
dstPtr = rDstPtr;
count = tRowBytes;
break;
case 2:
error = HEncode(&srcPtr, &dstPtr, imageWidth);
count = dstPtr - rowBuffer;
break;
default:
error = -3;
break;
}
if (error == noErr)
error = FSWrite(refNum, &count, rowBuffer);
*nextFileFree += count;
stripSize += count;
}
(*countHandle)[stripNum] = stripSize;
}
if (rowBuffer != NIL)
DisposPtr(rowBuffer);
tempErr = PutStripArrays(listHandle, offsetHandle, countHandle);
if (error == noErr)
error = tempErr;
return(error);
}
/* ---------------------------------------------------------------- */
void TFixOddRowBytes(bitMap)
BitMap *bitMap;
{
register Ptr dstPtr;
register Ptr srcPtr;
Int32 nLines;
Int16 line;
Int16 k;
nLines = bitMap->bounds.bottom - bitMap->bounds.top;
srcPtr = bitMap->baseAddr + nLines * (bitMap->rowBytes - 1) - 1;
dstPtr = bitMap->baseAddr + nLines * bitMap->rowBytes - 2;
for (line=nLines; line>0; line--)
{
for (k=0; k<bitMap->rowBytes-1; k++)
*dstPtr-- = *srcPtr--;
dstPtr--;
}
}
/* ---------------------------------------------------------------- */
void TUnfixOddRowBytes(bitMap)
BitMap *bitMap;
{
register Ptr dstPtr;
register Ptr srcPtr;
Int32 nLines;
Int16 line;
Int16 k;
nLines = bitMap->bounds.bottom - bitMap->bounds.top;
srcPtr = bitMap->baseAddr;
dstPtr = bitMap->baseAddr;
for (line=0; line<nLines; line++)
{
for (k=0; k<bitMap->rowBytes-1; k++)
*dstPtr++ = *srcPtr++;
srcPtr++;
}
}
/* ------------------------------------------------------------------- */
/* Local Subroutines */
/* ------------------------------------------------------------------- */
/*
* Remove the tag beginning at the specified offset. Reduce the size
* of the list accordingly.
*/
static OSErr DeleteTag(listHandle, pointer)
Handle listHandle;
Int32 pointer;
{
Int32 listSize;
Int16 tagNo;
Int16 tagType;
Int32 length;
Int32 nVals;
Int16 tagSize;
unsigned char *listPtr;
Int32 i;
OSErr error;
Handle tempHandle;
listSize = GetHandleSize(listHandle);
ParseTag(listHandle, pointer, &tagNo, &tagType, &nVals);
switch(tagType)
{
case BYTE:
length = nVals * BYTESIZE;
break;
case ASCII:
length = nVals * ASCIISIZE;
break;
case SHORT:
length = nVals * SHORTSIZE;
break;
case LONG:
length = nVals * LONGSIZE;
break;
case RATIONAL:
length = nVals * RATSIZE;
break;
}
tagSize = length + 8;
listPtr = *listHandle; /* DEREFERENCING HANDLE */
for (i=pointer; i<listSize-tagSize; i++)
listPtr[i] = listPtr[i + tagSize];
error = AllocHandleSize(listHandle, listSize - tagSize);
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Insert tag in list. This routine does not check for duplicates.
*/
static OSErr InsertTag(listHandle, pointer, tagNo, tagType, nVals, value)
Handle listHandle;
Int32 pointer;
Int16 tagNo;
Int16 tagType;
Int32 nVals;
unsigned char *value;
{
OSErr error;
Int32 listSize;
Int32 tagSize;
unsigned char *listPtr;
Int32 i;
Int32 length;
Handle tempHandle;
listSize = GetHandleSize(listHandle);
switch(tagType)
{
case BYTE:
length = nVals * BYTESIZE;
break;
case ASCII:
length = nVals * ASCIISIZE;
break;
case SHORT:
length = nVals * SHORTSIZE;
break;
case LONG:
length = nVals * LONGSIZE;
break;
case RATIONAL:
length = nVals * RATSIZE;
break;
default:
error = -3;
break;
}
tagSize = length + 8;
error = AllocHandleSize(listHandle, listSize + tagSize);
if (error == noErr)
{
listPtr = *listHandle; /* DEREFERENCING HANDLE */
for (i=listSize+tagSize-1; i>=pointer+tagSize; i--)
listPtr[i] = listPtr[i - tagSize];
listPtr += pointer;
*listPtr++ = (tagNo >> 8) & 0xff;
*listPtr++ = (tagNo) & 0xff;
*listPtr++ = (tagType >> 8) & 0xff;
*listPtr++ = (tagType) & 0xff;
*listPtr++ = (nVals >> 24) & 0xff;
*listPtr++ = (nVals >> 16) & 0xff;
*listPtr++ = (nVals >> 8) & 0xff;
*listPtr++ = (nVals) & 0xff;
for (i=0; i<length; i++)
*listPtr++ = value[i];
}
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Insert tag in list. value is stored in a handle block.
* This routine does not check for duplicates.
*/
static OSErr HdlInsertTag(listHandle, pointer, tagNo, tagType, nVals, valueHdl)
Handle listHandle;
Int32 pointer;
Int16 tagNo;
Int16 tagType;
Int32 nVals;
unsigned char **valueHdl;
{
OSErr error;
Int32 listSize;
Int32 tagSize;
unsigned char *listPtr;
Int32 i;
Int32 length;
Handle tempHandle;
listSize = GetHandleSize(listHandle);
switch(tagType)
{
case BYTE:
length = nVals * BYTESIZE;
break;
case ASCII:
length = nVals * ASCIISIZE;
break;
case SHORT:
length = nVals * SHORTSIZE;
break;
case LONG:
length = nVals * LONGSIZE;
break;
case RATIONAL:
length = nVals * RATSIZE;
break;
default:
error = -3;
break;
}
tagSize = length + 8;
error = AllocHandleSize(listHandle, listSize + tagSize);
if (error == noErr)
{
listPtr = *listHandle; /* DEREFERENCING HANDLE */
for (i=listSize+tagSize-1; i>=pointer+tagSize; i--)
listPtr[i] = listPtr[i - tagSize];
listPtr += pointer;
*listPtr++ = (tagNo >> 8) & 0xff;
*listPtr++ = (tagNo) & 0xff;
*listPtr++ = (tagType >> 8) & 0xff;
*listPtr++ = (tagType) & 0xff;
*listPtr++ = (nVals >> 24) & 0xff;
*listPtr++ = (nVals >> 16) & 0xff;
*listPtr++ = (nVals >> 8) & 0xff;
*listPtr++ = (nVals) & 0xff;
for (i=0; i<length; i++)
*listPtr++ = (&**valueHdl)[i];
}
return(error);
}
/* ------------------------------------------------------------------- */
static void ParseTag(listHandle, pointer, tagNo, tagType, nVals)
Handle listHandle;
Int32 pointer;
Int16 *tagNo;
Int16 *tagType;
Int32 *nVals;
{
unsigned char *listPtr;
listPtr = *listHandle + pointer; /* DEREFERENCING HANDLE */
*tagNo = ((UInt16)listPtr[0] << 8) + (UInt16)listPtr[1];
*tagType = ((UInt16)listPtr[2] << 8) + (UInt16)listPtr[3];
*nVals = ((UInt32)listPtr[4] << 24) + (UInt32)(listPtr[5] << 16) +
((UInt32)listPtr[6] << 8) + (UInt32)listPtr[7];
}
/* ------------------------------------------------------------------- */
/*
* Create and return handles to arrays containg the strip byte counts
* and strip offsets
*/
static OSErr GStripArrays(listHandle, offsetHandle, countHandle)
Handle listHandle;
Handle *offsetHandle;
Handle *countHandle;
{
OSErr error;
Int32 pointer;
Int16 tagNo;
Int16 tagType;
Int32 length;
Int32 numOffsets;
Int32 nVals;
Int32 tRowsPerStrip;
Int16 imageWidth;
Int16 imageLength;
Int16 compressType;
Int16 bitsPerSample;
Int32 theByteCount;
Int32 i;
UInt8 *temp8Ptr;
UInt16 *temp16Ptr;
UInt32 *temp32Ptr;
*countHandle = NIL;
*offsetHandle = NIL;
error = noErr;
/* .................................... */
if (error == noErr)
error = TFindTag(listHandle, &pointer, STRIP_OFFSETS_TAG) ?
noErr : -3;
if (error == noErr)
{
ParseTag(listHandle, pointer, &tagNo, &tagType, &numOffsets);
length = numOffsets * LONGSIZE;
error = AllocMemory(offsetHandle, length);
}
if (error == noErr)
{
HLock(*offsetHandle);
TGetTag(listHandle, pointer, **offsetHandle, length);
/* convert array bytes or shorts to array of longs in place */
switch(tagType)
{
case BYTE:
/* HANDLE DEREFERENCE */
temp8Ptr = (*(UInt8 **)(*offsetHandle)) + numOffsets - 1;
temp32Ptr = (*(UInt32 **)(*offsetHandle)) + numOffsets - 1;
for (i = numOffsets - 1; i >= 0; i--)
*temp32Ptr-- = *temp8Ptr--;
break;
case SHORT:
/* HANDLE DEREFERENCE */
temp16Ptr = (*(UInt16 **)(*offsetHandle)) + numOffsets - 1;
temp32Ptr = (*(UInt32 **)(*offsetHandle)) + numOffsets - 1;
for (i = numOffsets - 1; i >= 0; i--)
*temp32Ptr-- = *temp16Ptr--;
break;
case LONG:
break;
default:
error = -3;
break;
}
HUnlock(*offsetHandle);
}
/* .................................... */
if (error == noErr)
{
error = TFindTag(listHandle, &pointer, STRIP_BYTE_COUNTS_TAG) ? noErr : -3;
if (error == noErr)
{ /* STRIP_BYTE_COUNTS_TAG exists */
ParseTag(listHandle, pointer, &tagNo, &tagType, &nVals);
length = nVals * LONGSIZE;
error = AllocMemory(countHandle, length);
if (error == noErr)
{
HLock(*countHandle);
TGetTag(listHandle, pointer, **countHandle, length);
/* convert array bytes or shorts to array of longs in place */
switch(tagType)
{
case BYTE:
/* HANDLE DEREFERENCE */
temp8Ptr = (*(UInt8 **)(*countHandle)) + nVals - 1;
temp32Ptr = (*(UInt32 **)(*countHandle)) + nVals - 1;
for (i = nVals - 1; i >= 0; i--)
*temp32Ptr-- = *temp8Ptr--;
break;
case SHORT:
/* HANDLE DEREFERENCE */
temp16Ptr = (*(UInt16 **)(*countHandle)) + nVals - 1;
temp32Ptr = (*(UInt32 **)(*countHandle)) + nVals - 1;
for (i = nVals - 1; i >= 0; i--)
*temp32Ptr-- = *temp16Ptr--;
break;
case LONG:
break;
default:
error = -3;
break;
}
HUnlock(*countHandle);
}
}
else
{ /* STRIP_BYTE_COUNTS_TAG does not exist */
/* we are ok if file is not compressed and there is only one strip */
error = GStripParams(listHandle, &tRowsPerStrip, &imageWidth, &imageLength,
&compressType, &bitsPerSample);
/* nVals and length determined above */
if (error == noErr && compressType == 1 && numOffsets == 1)
{ /* OK. fake the count array */
error = AllocMemory(countHandle, length);
if (error == noErr)
{
theByteCount = (Int32)imageWidth * (Int32)imageLength *
(Int32)bitsPerSample / 8L;
**(Int32 **)(*countHandle) = theByteCount;
}
}
else
error = -3;
}
}
/* .................................... */
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Delete old tags (if they exist) and add new tags for
* StripByteCounts and StripOffsets. In all cases, offsetHandle and
* countHandle are disposed, if they are not NIL
*/
static OSErr PutStripArrays(listHandle, offsetHandle, countHandle)
Handle listHandle;
Handle offsetHandle;
Handle countHandle;
{
OSErr error;
Int32 pointer;
Int16 tagNo;
Int16 tagType;
Int32 length;
Int32 nVals;
if (TFindTag(listHandle, &pointer, STRIP_BYTE_COUNTS_TAG))
DeleteTag(listHandle, pointer);
if (TFindTag(listHandle, &pointer, STRIP_OFFSETS_TAG))
DeleteTag(listHandle, pointer);
error = countHandle == NIL ? -3 : noErr;
if (error == noErr)
{
length = GetHandleSize(countHandle);
nVals = length / LONGSIZE;
/*MoveHHi(countHandle);
HLock(countHandle);*/
error = TPutHdlTag(listHandle, STRIP_BYTE_COUNTS_TAG, LONG,
nVals, countHandle);
/*HUnlock(countHandle);*/
}
if (error == noErr)
error = offsetHandle == NIL ? -3 : noErr;
if (error == noErr)
{
length = GetHandleSize(offsetHandle);
nVals = length / LONGSIZE;
/*MoveHHi(offsetHandle);
HLock(offsetHandle);*/
error = TPutHdlTag(listHandle, STRIP_OFFSETS_TAG, LONG,
nVals, offsetHandle);
/*HUnlock(offsetHandle);*/
}
if (countHandle != NIL)
DisposHandle(countHandle);
if (offsetHandle != NIL)
DisposHandle(offsetHandle);
return(error);
}
/* ------------------------------------------------------------------- */
/*
* Read data from the tag data list (listHandle) and return the
* values. If the tags are missing, return -3 as error.
*/
static OSErr GStripParams(listHandle, tRowsPerStrip, imageWidth, imageLength,
compressType, bitsPerSample)
Handle listHandle;
Int32 *tRowsPerStrip;
Int16 *imageWidth;
Int16 *imageLength;
Int16 *compressType;
Int16 *bitsPerSample;
{
OSErr error;
OSErr tempError;
Int32 pointer;
tempError = TFindTag(listHandle, &pointer, ROWS_PER_STRIP_TAG) ?
noErr : -3;
if (tempError == noErr)
TGetTag(listHandle, pointer, tRowsPerStrip, (Int32)LONGSIZE);
else
*tRowsPerStrip = 0x40000000; /* default */
tempError = TFindTag(listHandle, &pointer, BITS_PER_SAMPLE_TAG) ?
noErr : -3;
if (tempError == noErr)
TGetTag(listHandle, pointer, bitsPerSample, (Int32)SHORTSIZE);
else
*bitsPerSample = 1; /* default */
tempError = TFindTag(listHandle, &pointer, COMPRESSION_TAG) ?
noErr : -3;
if (tempError == noErr)
TGetTag(listHandle, pointer, compressType, (Int32)SHORTSIZE);
else
*compressType = 1; /* default */
error = TFindTag(listHandle, &pointer, IMAGE_WIDTH_TAG) ?
noErr : -3;
if (error == noErr)
TGetTag(listHandle, pointer, imageWidth, (Int32)SHORTSIZE);
if (error == noErr)
error = TFindTag(listHandle, &pointer, IMAGE_LENGTH_TAG) ?
noErr : -3;
if (error == noErr)
TGetTag(listHandle, pointer, imageLength, (Int32)SHORTSIZE);
return(error);
}
/* ------------------------------------------------------------------- */
void SwapWord(val)
UInt16 *val;
{
*val = (*val >> 8) + (*val << 8);
}
/* ------------------------------------------------------------------- */
void SwapLong(val)
UInt16 val[2];
{
UInt16 temp;
temp = val[0];
val[0] = (val[1] >> 8) + (val[1] << 8);
val[1] = (temp >> 8) + (temp << 8);
}
/* ------------------------------------------------------------------- */